package com.blacktea.structuralpatterns.compositepattern.condition;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import com.blacktea.structuralpatterns.compositepattern.component.Composite;
import com.blacktea.structuralpatterns.compositepattern.component.Leaf;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @description: 登录条件验证类
 * @author: black tea
 * @date: 2023/3/22 18:29
 */
@Service
@Slf4j
public class LoginCondition<T> {

    public void check(T data){
        Composite<T> root = new Composite<>("root组件", null);
        AtomicLong startTime = new AtomicLong();

        Leaf<T> startLeaf = new Leaf<>("记录开始时间组件", (d)-> startTime.set(System.currentTimeMillis()));
        root.add(startLeaf);

        Composite<T> condition = new Composite<>("登录参数校验组合组件", null);

        Leaf<T> conditionObj = new Leaf<>("检查对象是否为空组件", (d) -> {
            if (d == null) {
                throw ExceptionUtil.wrapRuntime("对象不可以为空！");
            }
        });

        // 比如说存在username和password和timestamp，且timestamp不可以超出当前2分钟
        Leaf<T> conditionUsername = new Leaf<>("检查username组件", (d) -> {
            Map<String, Object> map = (Map<String, Object>) d;
            Object username = map.get("username");
            if (StrUtil.isEmptyIfStr(username)) {
                throw ExceptionUtil.wrapRuntime("用户名不可以为空！");
            }
        });

        Leaf<T> conditionPassword = new Leaf<>("检查password组件", (d) -> {
            Map<String, Object> map = (Map<String, Object>) d;
            Object password = map.get("password");
            if (StrUtil.isEmptyIfStr(password)) {
                throw ExceptionUtil.wrapRuntime("密码不可以为空！");
            }
        });

        Leaf<T> conditionTimestamp = new Leaf<>("检查时间戳组件", (d) -> {
            Map<String, Object> map = (Map<String, Object>) d;
            Long timestamp = (Long) map.get("timestamp");
            if (Validator.isEmpty(timestamp)) {
                throw ExceptionUtil.wrapRuntime("时间戳不可以为空！");
            }
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            long currentTimeMillis = System.currentTimeMillis();
            if (currentTimeMillis - timestamp > 60000 * 2) {
                throw ExceptionUtil.wrapRuntime("当前时间戳超时，请重新生成后再尝试！");
            }
        });

        condition.addAll(Arrays.asList(conditionObj, conditionUsername, conditionPassword, conditionTimestamp));
        root.add(condition);

        Leaf<T> endLeaf = new Leaf<>("记录结束时间组件", (d) ->{
            log.info("本次执行操作，总耗时{}毫秒。", System.currentTimeMillis() - startTime.get());
        });
        root.add(endLeaf);

        root.operation(data);
    }

}

